#ifndef _XGBA_MEM_H_
#define _XGBA_MEM_H_

#ifndef INLINE
#define INLINE static inline
#endif

#include <xgba.h>
#include <xgba_cpu.h>

INLINE uint32_t xgba_readu8(xgba_t*gba,uint32_t addr){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    return mem[addr&gba->mem_map_mask[m]];
}

INLINE uint32_t xgba_readu16(xgba_t*gba,uint32_t addr){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    return *(uint16_t*)(&mem[addr&gba->mem_map_mask[m]]);
}

INLINE uint32_t xgba_readu32(xgba_t*gba,uint32_t addr){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    return *(uint32_t*)(&mem[addr&gba->mem_map_mask[m]]);
}

INLINE uint32_t xgba_reads8(xgba_t*gba,uint32_t addr){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    return (int8_t)(gba->mem_map[m][addr&gba->mem_map_mask[m]]);
}

INLINE uint32_t xgba_reads16(xgba_t*gba,uint32_t addr){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    return *(int16_t*)(&mem[addr&gba->mem_map_mask[m]]);
}


INLINE void xgba_writeu8(xgba_t*gba,uint32_t addr,uint32_t value){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->w_mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    mem[addr&gba->w_mem_map_mask[m]] = value&0xff;
}

INLINE void xgba_writeu16(xgba_t*gba,uint32_t addr,uint32_t value){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->w_mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    *(uint16_t*)(&mem[addr&gba->w_mem_map_mask[m]]) = value&0xffff;
}

INLINE void xgba_writeu32(xgba_t*gba,uint32_t addr,uint32_t value){
    int m = (addr>>24) & 0xf;
    uint8_t *mem = gba->w_mem_map[m];
    gba->R[emu_state] |= (mem==gba->nullmem)<<EMU_STATE_MEMACCESS_ERR;
    *(uint32_t*)(&mem[addr&gba->w_mem_map_mask[m]]) = value;
}


#endif
